#ifndef _QUATER_H_
#define _QUATER_H_

#include "vector.h"
#include "matrix.h"

class quater
{
public:
	quater()
	{
		x=y=x=w=0;
	}
	quater(vector3& _asix,float _angle)
	{
        float half_angle = _angle*0.5f;
        float sin_a = (float)sin(half_angle);
        x = _asix.x*sin_a;
		y = _asix.y*sin_a;
		z = _asix.z*sin_a;
		w = (float)cos(half_angle);
	}
	/*quater(matrix4& _mtx)
	{
		float tr = _mtx.mat[0] + _mtx.mat[5] + _mtx.mat[10];
        if (tr > 0.0f)
		{
            x = _mtx.mat[6] - _mtx.mat[9];
			y = _mtx.mat[8] - _mtx.mat[2];
			x = _mtx.mat[1] - _mtx.mat[4];
			w = tr + 1.0f;
        }
		else
        if( (_mtx.mat[0] > _mtx.mat[5] ) && ( _mtx.mat[2] > _mtx.mat[10]) ) 
		{
            x = 1.0f + _mtx.mat[0] - _mtx.mat[5] - _mtx.mat[10];
			y = _mtx.mat[4] + _mtx.mat[1];
            z = _mtx.mat[8] + _mtx.mat[2];
			w = _mtx.mat[6] - _mtx.mat[9];
        }
		else 
        if ( _mtx.mat[5] > _mtx.mat[10] )
		{
            x = _mtx.mat[4] + _mtx.mat[1];
			y = 1.0f + _mtx.mat[5] - _mtx.mat[0] - _mtx.mat[10];
			z = _mtx.mat[9] + _mtx.mat[6];
			w = _mtx.mat[8] - _mtx.mat[2]; 
        }
		else
		{
            x = _mtx.mat[8] + _mtx.mat[2];
			y = _mtx.mat[9] + _mtx.mat[6];
            z = 1.0f + _mtx.mat[10] - _mtx.mat[0] - _mtx.mat[5];
			w = _mtx.mat[1] - _mtx.mat[4];
        }
	}*/
	 __forceinline operator matrix4()
	{
		matrix4 ret;
		
		ret.mat[0] = 1.0f-2.0f*(y*y + z*z);  ret.mat[1] = 2.0f*(x*y - w*z);         ret.mat[2]  = 2.0f*(x*z + w*y);
		ret.mat[4] = 2.0f*(x*y + w*z);       ret.mat[5] = 1.0f-2.0f*(x*x + z*z);    ret.mat[6]  = 2.0f*(y*z - w*x);
		ret.mat[8] = 2.0f*(x*z - w*y);       ret.mat[9] = 2.0f*(y*z + w*x);         ret.mat[10] = 1.0f-2.0f*(x*x + y*y);

		ret.mat[12] = 0.0f;
		ret.mat[13] = 0.0f;
		ret.mat[14] = 0.0f;
		ret.mat[3]  = 0.0f;
		ret.mat[7]  = 0.0f;
		ret.mat[11] = 0.0f;
		ret.mat[15] = 1.0f;

		/*float fTx  = 2.0*x;
        float fTy  = 2.0*y;
        float fTz  = 2.0*z;
        float fTwx = fTx*w;
        float fTwy = fTy*w;
        float fTwz = fTz*w;
        float fTxx = fTx*x;
        float fTxy = fTy*x;
        float fTxz = fTz*x;
        float fTyy = fTy*y;
        float fTyz = fTz*y;
        float fTzz = fTz*z;

        ret.mat[0] = 1.0-(fTyy+fTzz);
        ret.mat[1] = fTxy-fTwz;
        ret.mat[2] = fTxz+fTwy;
        ret.mat[4] = fTxy+fTwz;
        ret.mat[5] = 1.0-(fTxx+fTzz);
        ret.mat[6] = fTyz-fTwx;
        ret.mat[8] = fTxz-fTwy;
        ret.mat[9] = fTyz+fTwx;
        ret.mat[10] = 1.0-(fTxx+fTyy);*/

			
		return ret;
	}
	 __forceinline float dot(quater& _q)
	{
		return (x*_q.x + y*_q.y + z*_q.z + w*_q.w);
	}
	 __forceinline quater operator-(quater& _q)
	{
		quater ret;

		ret.x = x - _q.x;
		ret.y = y - _q.y;
		ret.z = z - _q.z;
		ret.w = w - _q.w;

		return ret;
	}
	 __forceinline quater operator+(quater& _q)
	{
		quater ret;

		ret.x = x + _q.x;
		ret.y = y + _q.y;
		ret.z = z + _q.z;
		ret.w = w + _q.w;

		return ret;
	}
	 __forceinline quater operator*(float _k)
	{
		quater ret;

		ret.x = x*_k;
		ret.y = y*_k;
		ret.z = z*_k;
		ret.w = w*_k;

		return ret;
	}
	static __forceinline quater lerp(quater& _q1,quater& _q2,float _k)
	{
		if(_q1.dot(_q2) < 0.0f)
		{
			return (_q1 - (_q2 + _q1) * _k);
		}
		else
		{
			return (_q1 + (_q2 - _q1) * _k);
		}
	}
private:
	float x,y,z,w;
};

#endif